const gulp = require("gulp");
// gulp core function
const { src, dest, series, parallel, watch } = require("gulp");
// gulp compress js
const uglify = require("gulp-uglify");
// gulp judgment
const gulpif = require("gulp-if");
// gulp compress css
const cleanCSS = require("gulp-clean-css");
// Delete Files
const del = require("delete");
// Refresh the browser in real time
const browserSync = require("browser-sync").create();
const reload = browserSync.reload;
// proxy
const { createProxyMiddleware } = require("http-proxy-middleware");
// According to html reference, files are merged
// const useref = require('gulp-useref');
// File merge
const concat = require("gulp-concat");
// rollup packaging, processing es6 modules
const { rollup } = require("rollup");
// rollup looks for node_modules module
const { nodeResolve } = require("@rollup/plugin-node-resolve");
// rollup converts commonjs module to es6 module
const commonjs = require("@rollup/plugin-commonjs");
// rollup code compression
const terser = require("rollup-plugin-terser").terser;
// rollup babel plugin, support the latest ES grammar
const babel = require("@rollup/plugin-babel").default;
// const gulpBabel = require('gulp-babel');
// Distinguish development and production environments
const production = process.env.NODE_ENV === "production" ? true : false;

const pkg = require("./package.json");
const banner = `/*! @preserve
 * ${pkg.name}
 * version: ${pkg.version}
 * https://github.com/mengshukeji/Luckysheet
 */`;

// uglify js Compression configuration https://github.com/mishoo/UglifyJS#minify-options
const uglifyOptions = {
	compress: {
		drop_console: true,
	},
};

// babel config
const babelConfig = {
	compact: false,
	babelHelpers: "bundled",
	exclude: "node_modules/**", // Only compile our source code
	plugins: [],
	presets: [
		[
			"@babel/preset-env",
			{
				useBuiltIns: "usage",
				corejs: 3,
				targets: {
					chrome: 58,
					ie: 11,
				},
			},
		],
	],
};

// file handler paths
const paths = {
	// static resources,contains index.html, fonts and images,and extension plugins dependency
	staticHtml: ["src/*.html"],
	staticFonts: ["src/fonts/**"],
	staticAssets: ["src/assets/**"],
	staticImages: ["src/plugins/images/*.png"],
	staticExpendPlugins: [
		"src/expendPlugins/**",
		"!src/expendPlugins/**/plugin.js",
	],
	staticDemoData: ["src/demoData/*.js"],
	staticCssImages: ["src/css/**", "!src/css/*.css"],

	// static resources dest
	destStaticHtml: ["dist"],
	destStaticFonts: ["dist/fonts"],
	destStaticAssets: ["dist/assets"],
	destStaticImages: ["dist/plugins/images"],
	destStaticExpendPlugins: ["dist/expendPlugins"],
	destStaticDemoData: ["dist/demoData"],
	destStaticCssImages: ["dist/css"],

	//core es module
	core: [
		"src/**/*.js",
		"!src/demoData/*.js",
		"src/expendPlugins/**/plugin.js",
		"!src/plugins/js/*.js",
	],

	//plugins src
	pluginsCss: ["src/plugins/css/*.css"],
	plugins: ["src/plugins/*.css"],
	css: ["src/css/*.css", "node_modules/flatpickr/dist/themes/light.css"],
	pluginsJs: [
		"node_modules/jquery/dist/jquery.min.js",
		"node_modules/uuid/dist/umd/uuid.min.js",
		"src/plugins/js/clipboard.min.js",
		"src/plugins/js/spectrum.min.js",
		"src/plugins/js/jquery-ui.min.js",
		"src/plugins/js/jquery.mousewheel.min.js",
		// 'src/plugins/js/numeral.min.js',
		"src/plugins/js/html2canvas.min.js",
		"src/plugins/js/localforage.min.js",
		"src/plugins/js/lodash.min.js",
		"src/plugins/js/jstat.min.js",
		"src/plugins/js/crypto-api.min.js",
		"src/plugins/js/jquery.sPage.min.js",
	],

	//plugins concat
	concatPluginsCss: "pluginsCss.css",
	concatPlugins: "plugins.css",
	concatCss: "luckysheet.css",
	concatPluginsJs: "plugin.js",

	//plugins dest
	destPluginsCss: ["dist/plugins/css"],
	destPlugins: ["dist/plugins"],
	destCss: ["dist/css"],
	destPluginsJs: ["dist/plugins/js"],

	// Package directory
	dist: "dist",
};

// Clear the dist directory
function clean() {
	return del([paths.dist]);
}

// proxy middleware
const apiProxy = createProxyMiddleware("/luckysheet/", {
	target: "http://luckysheet.lashuju.com/", // set your server address
	changeOrigin: true, // for vhosted sites
	ws: true, // proxy websockets
});

// Static server
function serve(done) {
	browserSync.init(
		{
			server: {
				baseDir: paths.dist,
				middleware: [apiProxy], //proxy
			},
			ghostMode: false, //默认true，滚动和表单在任何设备上输入将被镜像到所有设备里，会影响本地的协同编辑消息，故关闭
		},
		done
	);
}

// Monitoring file changes
function watcher(done) {
	watch(paths.core, { delay: 500 }, series(core, reloadBrowser));

	// watch plugins and css
	watch(paths.pluginsCss, { delay: 500 }, series(pluginsCss, reloadBrowser));
	watch(paths.plugins, { delay: 500 }, series(plugins, reloadBrowser));
	watch(paths.css, { delay: 500 }, series(css, reloadBrowser));
	watch(paths.pluginsJs, { delay: 500 }, series(pluginsJs, reloadBrowser));

	// watch static
	watch(
		paths.staticHtml,
		{ delay: 500 },
		series(copyStaticHtml, reloadBrowser)
	);
	watch(
		paths.staticFonts,
		{ delay: 500 },
		series(copyStaticFonts, reloadBrowser)
	);
	watch(
		paths.staticAssets,
		{ delay: 500 },
		series(copyStaticAssets, reloadBrowser)
	);
	watch(
		paths.staticImages,
		{ delay: 500 },
		series(copyStaticImages, reloadBrowser)
	);
	watch(
		paths.staticExpendPlugins,
		{ delay: 500 },
		series(copyStaticExpendPlugins, reloadBrowser)
	);
	watch(
		paths.staticDemoData,
		{ delay: 500 },
		series(copyStaticDemoData, reloadBrowser)
	);
	watch(
		paths.staticCssImages,
		{ delay: 500 },
		series(copyStaticCssImages, reloadBrowser)
	);

	done();
}

// Refresh browser
function reloadBrowser(done) {
	reload();

	done();
}

//Package the core code
async function core_rollup() {
	const bundle = await rollup({
		input: "src/index.js",
		plugins: [
			nodeResolve(), // tells Rollup how to find date-fns in node_modules
			commonjs(), // converts date-fns to ES modules
			// postcss({
			// 	plugins: [],
			// 	extract: true,
			// 	// minimize: isProductionEnv,
			// }),
			production && terser(), // minify, but only in production
			babel(babelConfig),
		],
	});

	bundle.write({
		file: "dist/luckysheet.umd.js",
		format: "umd",
		name: "luckysheet",
		sourcemap: true,
		inlineDynamicImports: true,
		banner: banner,
	});

	if (production) {
		bundle.write({
			file: "dist/luckysheet.esm.js",
			format: "esm",
			name: "luckysheet",
			sourcemap: true,
			inlineDynamicImports: true,
			banner: banner,
		});
	}
}

async function core() {
	await require("esbuild").buildSync({
		format: "iife",
		globalName: "luckysheet",
		entryPoints: ["src/index.js"],
		bundle: true,
		minify: production,
		banner: { js: banner },
		target: ["es2015"],
		sourcemap: true,
		outfile: "dist/luckysheet.umd.js",
		logLevel: "error",
	});
}

// According to the build tag in html, package js and css
function pluginsCss() {
	return src(paths.pluginsCss)
		.pipe(concat(paths.concatPluginsCss))
		.pipe(gulpif(production, cleanCSS()))
		.pipe(dest(paths.destPluginsCss));
}

function plugins() {
	return src(paths.plugins)
		.pipe(concat(paths.concatPlugins))
		.pipe(gulpif(production, cleanCSS()))
		.pipe(dest(paths.destPlugins));
}

function css() {
	return src(paths.css)
		.pipe(concat(paths.concatCss))
		.pipe(gulpif(production, cleanCSS()))
		.pipe(dest(paths.destCss));
}

function pluginsJs() {
	return src(paths.pluginsJs)
		.pipe(concat(paths.concatPluginsJs))
		.pipe(gulpif(production, uglify(uglifyOptions)))
		.pipe(dest(paths.destPluginsJs));
}

// Copy static resources
function copyStaticHtml() {
	return src(paths.staticHtml).pipe(dest(paths.destStaticHtml));
}
function copyStaticFonts() {
	return src(paths.staticFonts).pipe(dest(paths.destStaticFonts));
}
function copyStaticAssets() {
	return src(paths.staticAssets).pipe(dest(paths.destStaticAssets));
}
function copyStaticImages() {
	return src(paths.staticImages).pipe(dest(paths.destStaticImages));
}
function copyStaticExpendPlugins() {
	return src(paths.staticExpendPlugins).pipe(
		dest(paths.destStaticExpendPlugins)
	);
}
function copyStaticDemoData() {
	return src(paths.staticDemoData).pipe(dest(paths.destStaticDemoData));
	// .pipe(gulpBabel({
	//     presets: ['@babel/env']
	// }))
	// .pipe(gulp.dest('dist'));
}
function copyStaticCssImages() {
	return src(paths.staticCssImages).pipe(dest(paths.destStaticCssImages));
}

const dev = series(
	clean,
	parallel(
		pluginsCss,
		plugins,
		css,
		pluginsJs,
		copyStaticHtml,
		copyStaticFonts,
		copyStaticAssets,
		copyStaticImages,
		copyStaticExpendPlugins,
		copyStaticDemoData,
		copyStaticCssImages,
		core
	),
	watcher,
	serve
);
const build = series(
	clean,
	parallel(
		pluginsCss,
		plugins,
		css,
		pluginsJs,
		copyStaticHtml,
		copyStaticFonts,
		copyStaticAssets,
		copyStaticImages,
		copyStaticExpendPlugins,
		copyStaticDemoData,
		copyStaticCssImages,
		core
	)
);

exports.dev = dev;
exports.build = build;
exports.default = dev;
